package desktop.core.bar;

import pulpcore.Stage;
import pulpcore.animation.Timeline;
import pulpcore.animation.event.AddSpriteEvent;
import pulpcore.scene.Scene2D;
import pulpcore.sprite.Group;
import pulpcore.sprite.ImageSprite;
import desktop.core.square.Square;

public class Bar extends Group implements Cloneable {

	private Timeline timeline = null;
	private String background = "Bar.jpg";
	private double speed;

	private final int column;
	private final int row;
	private Square[][] squares;

	public Bar(double x, double y, double w, double h, int column, int row,
			Square[][] squares, double gravity) {
		super(x, y, w, h);
		this.add(new ImageSprite(background, 0, 0, this.width.get(),
				this.height.get()));
		this.column = column;
		this.row = row;
		this.squares = squares;
		for (int i = 0; i < this.column; i++) {
			for (int j = 0; j < this.row; j++) {

				timeline = new Timeline();
				timeline.addEvent(new AddSpriteEvent(this, squares[i][j], 0));
				((Scene2D) Stage.getScene()).addTimeline(timeline);

			}
		}
		this.speed = gravity;
	}

	public int getColumn() {
		return column;
	}

	public int getRow() {
		return row;
	}

	public Square getSquare(int columnId, int rowId) {
		return this.squares[columnId][rowId];
	}

	public double getSpeed() {
		return speed;
	}

	public void setSpeed(double speed) {
		this.speed = speed;
	}

	public boolean containsPoint(double xCheck, double yCheck) {
		return (this.x.get() <= xCheck)
				&& (xCheck <= this.x.get() + this.width.get())
				&& (this.y.get() <= yCheck)
				&& (yCheck <= this.y.get() + this.height.get());
	}

	/**
	 * 由PlayingField考虑边界
	 */
	public Timeline moveLeft(int elapsedTime) {
		double oldX = this.x.get();
		double newX = this.x.get() - this.getWidthUnit();
		timeline = new Timeline();
		timeline.animate(this.x, oldX, newX, elapsedTime);
		((Scene2D) Stage.getScene()).addTimeline(timeline);

		timeline = new Timeline();
		timeline.animate(this.x, oldX, newX, elapsedTime);
		return timeline;
	}

	public Timeline moveRight(int elapsedTime) {
		double oldX = this.x.get();
		double newX = this.x.get() + this.getWidthUnit();
		timeline = new Timeline();
		timeline.animate(this.x, oldX, newX, elapsedTime);
		((Scene2D) Stage.getScene()).addTimeline(timeline);

		timeline = new Timeline();
		timeline.animate(this.x, oldX, newX, elapsedTime);
		return timeline;
	}

	public Timeline moveDownDirectly(double bottom, int elapsedTime) {
		double oldY = this.y.get();
		double newY = bottom;
		timeline = new Timeline();
		timeline.animate(this.y, oldY, newY, elapsedTime);
		((Scene2D) Stage.getScene()).addTimeline(timeline);

		timeline = new Timeline();
		timeline.animate(this.y, oldY, newY, elapsedTime);
		return timeline;
	}

	public Timeline dropByGravity(int elapsedTime) {
		double oldY = this.y.get();
		this.speed *= 1 + 0.01;
		double newY = this.y.get() + this.speed * elapsedTime;
		timeline = new Timeline();
		timeline.animate(this.y, oldY, newY, elapsedTime);
		((Scene2D) Stage.getScene()).addTimeline(timeline);

		timeline = new Timeline();
		timeline.animate(this.y, oldY, newY, elapsedTime);
		return timeline;
	}

	public Timeline shift() {
		// view
		final int Duration = 62;
		timeline = new Timeline();
		Timeline t = new Timeline();
		for (int i = 0; i < this.column; i++) {
			for (int j = 0; j < this.row - 1; j++) {
				Square square = this.getSquare(i, j);

				double oldY = this.y.get();
				double newY = square.y.get() + this.getHeightUnit();
				timeline.animate(square.y, oldY, newY, Duration);
				t.animate(square.y, oldY, newY, Duration);

			}
			Square square = this.getSquare(i, this.row - 1);
			double oldY = this.y.get();
			double newY = 0;
			timeline.animate(square.y, oldY, newY, Duration);
			t.animate(square.y, oldY, newY, Duration);
		}
		((Scene2D) Stage.getScene()).addTimeline(timeline);

		// model
		for (int i = 0; i < this.column; i++) {
			Square square = this.squares[i][this.row - 1];
			for (int j = this.row - 1; j > 0; j--) {
				this.squares[i][j] = this.squares[i][j - 1];
			}
			this.squares[i][0] = square;
		}
		return timeline;
	}

	public double getWidthUnit() {
		return this.width.get() / this.column;
	}

	public double getHeightUnit() {
		return this.height.get() / this.row;
	}

	public double getXLeftTop() {
		return this.x.get();
	}

	public double getYLeftTop() {
		return this.y.get();
	}

	public double getXLeftBottom() {
		return this.x.get();
	}

	public double getYLeftBottom() {
		return this.y.get() + this.height.get();
	}

	public double getXRightTop() {
		return this.x.get() + this.width.get();
	}

	public double getYRightTop() {
		return this.y.get();
	}

	public double getXRightBottom() {
		return this.x.get() + this.width.get();
	}

	public double getYRightBottom() {
		return this.y.get() + this.height.get();
	}

	@Override
	public Object clone() throws CloneNotSupportedException {
		Square[][] tmpSquares = new Square[this.column][this.row];
		for (int i = 0; i < this.column; i++) {
			for (int j = 0; j < this.row; j++) {
				tmpSquares[i][j] = (Square) this.squares[i][j].clone();
			}
		}
		return new Bar(this.x.get(), this.y.get(), this.width.get(),
				this.height.get(), this.column, this.row, tmpSquares,
				this.speed);
	}

}